/*
 * Created on 2006-7-1
 */
package field;

import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;

public class FormatConverter {

	File inFilePath;

	File outFilePath;

	BufferedReader br;

	BufferedWriter bw;

	HashMap objects;

	int currentTS;

	String[] lastRecord;

	int numObjects;

	int INSERT = 0;

	int UPDATE = 1;

	boolean eof = false;

	public FormatConverter(String filepath, String outFilePath) {

		this.objects = new HashMap();
		this.inFilePath = new File(filepath);
		this.outFilePath = new File(outFilePath);
		try {
			FileReader fr = new FileReader(this.inFilePath);
			this.br = new BufferedReader(fr);
		} catch (FileNotFoundException e) {
			System.out
					.println("In MessageGenerator(), file not found exception");
			System.exit(-1);
		}

		try {

			FileWriter fw = new FileWriter(this.outFilePath);
			this.bw = new BufferedWriter(fw);
		} catch (IOException e) {
			System.out.println("In MessageGenerator(), IO exception");
			System.exit(-1);
		}
	}

	public String[] getOneRecord() {
		String line = null;
		try {
			line = this.br.readLine();
			if (line != null) {
				return line.split("\t");
			} else {
				this.eof = true;
				return null;
			}
		} catch (IOException e) {
			System.out.println("in time0process, IOException");
			System.exit(-1);
		}
		return null;
	}

	public void time0process() {
		this.currentTS = 0;

		String[] aRecord = this.getOneRecord();
		if (aRecord != null) {
			int readTS = Integer.parseInt(aRecord[4]);
			while (aRecord != null && readTS == 0) {
				int oid = Integer.parseInt(aRecord[1]);
				double px = Double.parseDouble(aRecord[5]);
				double py = Double.parseDouble(aRecord[6]);
				Point2D p = new Point2D.Double(px, py);
				Point2D nextp = new Point2D.Double(px, py);
				Velocity v = new Velocity(0, 0);
				Cell cid = new Cell(0, 0, 1);// fake cid.
				MovingObject mo = new MovingObject(oid, 5, p, v, 0, cid, null);
				mo.nextP = nextp;
				this.objects.put(new Integer(mo.oid), mo);
				aRecord = this.getOneRecord();
				if (aRecord != null) {
					readTS = Integer.parseInt(aRecord[4]);
				}
			}
			// the last record read in is for time step 1, so we need to keep
			// it.
			this.lastRecord = aRecord;

			this.numObjects = this.objects.size();
			System.out.println("# of objects:" + this.numObjects);
		} else {
			System.out.println("in time0process, get null record");
			System.exit(-1);
		}

	}

	public void preProcessNTS() {
		String[] aRecord = this.lastRecord;
		int nextTS = this.currentTS + 1;
		int readTS = Integer.parseInt(aRecord[4]);
		while (aRecord != null && readTS == nextTS) {
			if (aRecord[0].equals("disappearpoint")) {
				// do nothing, since a newpoint record of this object will come.
			} else {
				int oid = Integer.parseInt(aRecord[1]);
				double px = Double.parseDouble(aRecord[5]);
				double py = Double.parseDouble(aRecord[6]);
				Point2D nextLoc = new Point2D.Double(px, py);
				MovingObject mo = (MovingObject) this.objects.get(new Integer(
						oid));
				mo.nextP = nextLoc;
				// calculate the speed
				double deltaX = px - mo.getCenterX();
				double deltaY = py - mo.getCenterY();
				Velocity speed = new Velocity(deltaX, deltaY); // because delta
				// time step is 1.
				if (this.currentTS == 0) {
					mo.speed = speed;
					// System.out.println("object " + mo.oid + " has speed "
					// + mo.v.oneValueSpeed());
				} else {
					if (mo.speed.sameWith(speed)) {
						// doing nothing
					} else {
						// System.out
						// .println("object " + mo.oid
						// + " changes speed from " + mo.v + " to"
						// + speed);
					}
					mo.speed = speed;
				}
			}
			aRecord = this.getOneRecord();
			if (aRecord != null) {
				readTS = Integer.parseInt(aRecord[4]);
			}
		}
		// the last record read in is for time step 1, so we need to keep it.
		this.lastRecord = aRecord;
		this.currentTS++;
	}

//	public void postProcessNTS() {
//		// this.currentTS++;
//		for (int i = 0; i < this.objects.size(); i++) {
//			MovingObject mo = (MovingObject) this.objects.get(new Integer(i));
//			mo.currP = mo.nextP;
//		}
//	}

	public void printAllObjects() {
		for (int i = 0; i < this.objects.size(); i++) {
			MovingObject mo = (MovingObject) this.objects.get(new Integer(i));
			String arecord = this.objectRecord(mo);
			// System.out.println(arecord);
			try {
				this.bw.write(arecord + "\n");
			} catch (IOException e) {
				System.out.println("In printAllObjects(), IO exception");
				System.exit(-1);
			}

		}
	}

	public String objectRecord(MovingObject mo) {
		String ps = this.currentTS + " ";
		if (this.currentTS == 0) {
			ps = " " + ps + this.INSERT;
		} else {
			ps = ps + this.UPDATE;
		}
		ps = ps + " " + mo.oid;
		ps = ps + " " + (float) mo.getCenterX() / 100 + " "
				+ (float) mo.getCenterY() / 100;
		ps = ps + " " + (float) mo.nextP.getX() / 100 + " "
				+ (float) mo.nextP.getY() / 100;
		return ps;
	}

	public void convert() {
		this.time0process();// create all the objects.
		this.printAllObjects();
		int count = 0;

		while (!this.eof) {
			this.preProcessNTS();
			this.printAllObjects();
//			this.postProcessNTS();
			count++;
			System.out.println("ts:" + count);
		}

		try {
			this.bw.flush();
		} catch (IOException e) {
			System.out.println("In convert(), IO exception");
			System.exit(-1);
		}

	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		String inFile;
		String outFile;

		if (args.length != 2) {
			System.out.println("usage: inputFile outputFile");
			System.exit(-1);
		} else {
			inFile = args[0];
			outFile = args[1];
			FormatConverter fc_o = new FormatConverter(inFile, outFile);
			fc_o.convert();
			System.out.println("convert done");
		}

	}

}
